package cn.geminis.lowcode.processor;

import cn.geminis.lowcode.annotation.GeminisApplication;
import cn.geminis.lowcode.compiler.code.*;
import cn.geminis.lowcode.utils.Flags;
import cn.geminis.lowcode.utils.Utils;

import javax.lang.model.element.Element;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Map;

/**
 * @author puddi
 */
public class GeminisApplicationProcessor implements BaseProcessor {

    @Override
    public Class<? extends Annotation> getSupportAnnotation() {
        return GeminisApplication.class;
    }

    @Override
    public void process(Element element) {
        var annotation = element.getAnnotation(GeminisApplication.class);
        var basePackage = annotation.basePackage();
        var clazz = new LcClass(element);
        addAnnotations(clazz, basePackage);
        addMainMethod(clazz);

        Utils.setProjectRootPackage(clazz.getPackagee().getName());

        Utils.noteMessage(Utils.getElementQualifiedName(element) + " Enhanced");
    }

    private void addAnnotations(LcClass clazz, String packageName) {
        clazz.appendAnnotation(new LcAnnotation(
                "org.springframework.boot.autoconfigure.SpringBootApplication"
        ));
        clazz.appendAnnotation(new LcAnnotation(
                "org.springframework.boot.autoconfigure.domain.EntityScan",
                Map.of("", packageName)
        ));
        clazz.appendAnnotation(new LcAnnotation(
                "org.springframework.context.annotation.ComponentScan",
                Map.of("", packageName)
        ));
        clazz.appendAnnotation(new LcAnnotation(
                "org.springframework.cloud.openfeign.EnableFeignClients",
                Map.of("", packageName)
        ));
    }

    private void addMainMethod(LcClass clazz) {
        clazz.append(
                new LcMethod(
                        new LcModifier(Flags.PUBLIC | Flags.STATIC),
                        "VOID",
                        "main",
                        List.of(new LcVariable("java.lang.String[]", "args")),
                        List.of(),
                        List.of(
                                new LcApply(
                                        "org.springframework.boot.SpringApplication.run",
                                        new LcIdent(clazz.getJdkTree().getSimpleName() + ".class"),
                                        new LcIdent("args")
                                ).exec()
                        )
                )
        );
    }
}